import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.util.*;
import java.util.zip.*;
import java.io.*;

/**
 * 用正确的私钥解密真实的EP
 */
public class DecryptRealEP {
    
    // 真实的EP（从加密数据.md）
    private static final String EP_BASE64 = "qt0AJsNLEfayUx7S15jLfmQvMOpW6JJ+jCoxeXxn676R2OiN6xpLIQWSYe8ETFUF4+AaGrVY1wMCdyUPVaHM0J+8m+q/PUFgbiP3N8xSKQc4lIzzZuckbybYiFuLbEhcblmy162S5B70UJxzB6grhIVpsG/h0uw+JPaS2yTPpPVCiN/SImdOw2g12cun6niAwRZSQktZikzzbjwkRoiO8ehrwlAFJircnT1/1zba2oaGXLc/yU6cM2vWgJdyyoXJF4Mo/5XNBTDT+8yr1hPC5MKHWcTBB/isrRTD5CczInLgXHl48KKz18GkpPM7MML1GHb4pIjfTvu8hv/SLLW0sg==";
    
    // 真实的data
    private static final String DATA_BASE64 = "wHBy2LDIay6WCgEybO8bw/5OxmVd4N++OJpwr/Tgjw+TA8iZ4HAy4bN8UWtwmeGz+dqU/zX6myCireq+q465rqUqpXLhma2aEPqTaNvUTv/Y71kVpkMBkgrjMnVkIi/iBV5eKsrTPfLWO8bt0mSbLM8ghswC2m2YRInkqWXHrc8Nw0JsNjwCllOUdtwe3NuIx8oQuQ2fqj1G3g3xMp6B4sWBNAo+SjTNuKnS4chvbaD3RYnGvSLyNYu+sqbKeRNofCwVn0lVrjCAGtC9d5nqhFiGw0vWksPfmCRn7vRsl7LnqcXb+Fal/hhREBsaRJdMrst3vOEeQI6pt3RGKZ3VOsliNziKbLiNnXp2zY2fin32okAFwIOczPgeQA1yAM4FCnuT9FYAMn5ecAOY7WFhJPcOqVThy0giCJrBzpIzEHXTin+BWBO1PR8wMzBqpf6us9mhBZGzu40mzVN34xXK646aMr8f2DcD9yGO20v5icEz3OUcAeayMq+YKmBoypmvQUnaGa8pjr7RfvvajY+7pu6QHqRAQ3NLY1KjIoT3PKjabb7owQ1Txw5+Ajfjen7VEeF/Dq03nPMtNOpqD3tCdWDHWir+akJcEPtPzK4Bo2K3FrLBZt2igZD6/04jtwoAojHibKqUM1Rj5h2iijH65eAU1XKTpqDPNtcP5lwa1bFNV+GvuzHM+N4gcoxiELhQeG7xiUcsZrJvadkDO2z+If9vLkXTSdMKrqozUjLRapyXpULcVL8negHnj+2vKZVdoGiDhXlm23XDFjLY91ZqX2eGfGNmpJxftl83N6q4dyXpzD2gR/chHfm0CukVlL8P8aPAfEDcAsyQETc5oVLzetGVSkGBbQl+axZu8U2Ap9CXaTi1b2VcI3he19nvgG8XEFnwP6Tbicm5PDDsiRjo2MRqfuPLWkcSHTmBlS6w8yrzAvth9x/bBLg8XLs8M/B/dKSfOa9sbptfTMmEuuhWbnqCyqnFSUt8lsFlcUbJdK02TcMbd789pANnrKTTfFeOUehu5XReHng4DfV7f6boQmJPnZfwuR8qFwp7vwme235RTloktlkQu/2QFl2LmCv+/8Za43dEdFba9Ae6I1p+50zunyIjGTE6/9RT+g/zgagzgV/qDDSM5VF6E2Ic62W/KkpfSPMHAk5Jwg0LlsSMnFXYCynZoDZ5M8s62V15VaEII3s/6wPCu4lba/BxPanRtw60EVsvrJ7B0mnG+hcW8AGVeG1ZBIhgPH887/bY+05b0MnSkhjlrys8GKSaukVbtnrLJmjePt+LdLe6tH2NTwxjbHhJR028ZWaQKvdC5BD2hRflDMBPKL68D6YJ2bitqnKKdEqYHdCMXtOXh68XUqwfkoF3phQtYHyrqF4Wsgukf3/gAlt/yF0dXFTIUzoDTc34MEAaLFENVFDt4PUnYw2SRT8i/bhi3tcavu6Hnjs=";
    
    // 正确的私钥（来自a7证书）
    private static final String PRIVATE_KEY_BASE64 = 
        "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCz8JyumzBRR1njdxPzCFpqWXrAUBiC4ycTbTDdWdpZkciwiXU5s/OxF5i7l+Hvwc9Ggjph/PKo7PpWhxZpzyEGpd6yVN9jAjJOt23o2TesgK8L/DAMhdJL8gNxKAQumbGF+ebMbcS8jWLxvDAqpmnEW8VdCLEjF6uqOPtcDmIkBF83W6oaeu32DzTr/NS16sUGQKxlflo9qPOl7VtcIsbR52klKK4uIyY23tWCouiyG84c/Uit+PleD5EYUGEu3p7IAAG5uJNzeUd0UjZDhy6x7ue+kGgcCmCNQ4zSS/bQHMknalwqJUvUSxtIf8dq+/D78m7d4Zt9n9ZD27t4Z2jHAgMBAAECggEAAr15RVdrpvE1NzeLADpyVghCzEbr+KJI6AzTn6tMneyQZ8/QDy7kWSAI3WJ0uFf1Nhepl/BoKZZiQYsRFk9nK1i/SWvtcu6HoZc9fzw/ksrq333ZpXcsOqfW0ZRQa/0/LNEfaKGLS2vDw/afrSaXmbvkB4SoXeZwYMk5Wq+FYxL/alrNpg/lzdvBlsCsTDA0G2RZrUVaO5yRTLRisBU+i8yORgnGkEwWvKpZYSFogCHSiYHiNXFy//C+sYWlK7DjmG8/+krKhqBRRfdeg7LFThHQpbEGTtueD57jw0PCo2yr6dqTvW9Qys+aWVNJk7RHNaI0yBFKWPadaHi3/olzkQKBgQDmz/FDpztS0fjKDIOjgDyE76Z6dRFenmKJM1eOFt+MniY6/vi4ylU51/Etm4k6dNJ1MVBoFfyT9X0U/4k7GNNUfIxMCJztUgY6EaCCt+09wk8pIvmOlRCmtxGwvmVC4nJVgUj3XJQ+wseblAkkW0+IuT3GKX0CdKFMU4q9aucLYwKBgQDHk3rQ8Ae4ci4oj+MehRI29SNpcXG6OHbrZ2EdsgqiFC1o/qv0269jtmCP7IqkGMdhTQrVetTHjZNZJH2bvUZ4o/0YT2+TTFPIkTb2/a0txUTBTKrbnAdXh/iPFZAGvBROEDN0MNKo/vGAfi0K836DeTyBIaYongm66Rn6pwnUTQKBgBveVaougfoxAhIbSrWuISCH8xjsE6nSA+G/Aj5Uwq8u1TzgVlWxkHLIgQVZt0sImfSufJ/kr7eJt42WgRJSoAmedC4mCBSbh8bxI+lEne+MC5TS9UDi/Ly0c/1cL8vQna93ScEcO4YMbJ97U1NBdyvx+eR4U/C89lDJ8YGHa9gzAoGAQ6sYsHFCXOKyDeTDoFyEUYgKqrzhT7/HaofR4Oy2OEBZKUl4anx2WnvC/+m3FG6mY7JoovuT29mABXCe+khR9aO8tBpy/WGa4t2B4nse1e8WIehp4i5kOuSKfZFVFUN+Kv3JRHMtakmO/v9JLHZlBhT8U9hh61GygOJ6gYdTiN0CgYAFz9iPy/xqLOUwiTNp3ImzhdZo9ol3Qlr9CfMWMFHqRA5AyYvly9ZzxTpUCpSA+qz6OXqAjJ0bhGQxW2KHpmcTyNGOPPca2vCaW8Mb1NTQueXpUBqX7alIkrRjUUyULteLb8FtyYl7mR3TVIu3FoO5anNwDZ+2y7R9WUEiOzY3NA==";
    
    public static void main(String[] args) {
        System.out.println("\n" + "=".repeat(80));
        System.out.println("                用正确的私钥解密真实的EP");
        System.out.println("=".repeat(80) + "\n");
        
        try {
            // 加载私钥
            byte[] privateKeyBytes = Base64.getDecoder().decode(PRIVATE_KEY_BASE64);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
            System.out.println("✅ 私钥加载成功\n");
            
            // 解码EP
            byte[] epEncrypted = Base64.getDecoder().decode(EP_BASE64);
            System.out.println("EP加密数据长度: " + epEncrypted.length + " 字节\n");
            
            // 尝试所有可能的RSA解密算法
            String[] algorithms = {
                "RSA/ECB/PKCS1Padding",
                "RSA/ECB/OAEPPadding",
                "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING",
                "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING",
                "RSA/ECB/NoPadding"
            };
            
            byte[] epDecrypted = null;
            String successAlgorithm = null;
            
            System.out.println("-".repeat(80));
            for (String algorithm : algorithms) {
                System.out.println("尝试算法: " + algorithm);
                try {
                    Cipher cipher = Cipher.getInstance(algorithm);
                    cipher.init(Cipher.DECRYPT_MODE, privateKey);
                    byte[] result = cipher.doFinal(epEncrypted);
                    
                    System.out.println("  ✅ 解密成功！长度: " + result.length + " 字节");
                    epDecrypted = result;
                    successAlgorithm = algorithm;
                    break;
                    
                } catch (Exception e) {
                    System.out.println("  ❌ 失败: " + e.getMessage());
                }
            }
            System.out.println("-".repeat(80));
            
            if (epDecrypted == null) {
                System.err.println("\n❌ 所有算法都失败了！");
                return;
            }
            
            System.out.println("\n🎉 EP解密成功！使用算法: " + successAlgorithm);
            System.out.println("\n" + "=".repeat(80));
            System.out.println("EP解密结果分析");
            System.out.println("=".repeat(80) + "\n");
            
            analyzeEPStructure(epDecrypted);
            
            // 尝试用EP中的密钥解密data
            System.out.println("\n" + "=".repeat(80));
            System.out.println("尝试用EP密钥解密data");
            System.out.println("=".repeat(80) + "\n");
            
            tryDecryptData(epDecrypted);
            
        } catch (Exception e) {
            System.err.println("❌ 错误: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    private static void analyzeEPStructure(byte[] data) {
        System.out.println("总长度: " + data.length + " 字节\n");
        
        System.out.println("完整HEX数据:");
        printHexDump(data);
        
        System.out.println("\n" + "-".repeat(80));
        System.out.println("结构推测:");
        System.out.println("-".repeat(80));
        
        // 提取可能的密钥和IV
        if (data.length >= 32) {
            byte[] possibleKey = Arrays.copyOfRange(data, 0, 32);
            System.out.println("\n字节[0:32] - 可能的AES-256密钥:");
            System.out.println("  " + bytesToHex(possibleKey));
        }
        
        if (data.length >= 48) {
            byte[] possibleIV = Arrays.copyOfRange(data, 32, 48);
            System.out.println("\n字节[32:48] - 可能的AES IV (16字节):");
            System.out.println("  " + bytesToHex(possibleIV));
        }
        
        if (data.length > 48) {
            System.out.println("\n字节[48:" + data.length + "] - 其他数据 (" + (data.length - 48) + "字节):");
            System.out.println("  " + bytesToHex(Arrays.copyOfRange(data, 48, Math.min(data.length, 80))));
            if (data.length > 80) {
                System.out.println("  ... (省略)");
            }
        }
    }
    
    private static void tryDecryptData(byte[] epData) {
        byte[] dataEncrypted = Base64.getDecoder().decode(DATA_BASE64);
        
        // 提取密钥和IV的不同组合
        byte[][] keyOptions = new byte[0][];
        byte[][] ivOptions = new byte[0][];
        
        if (epData.length >= 32) {
            keyOptions = new byte[][] {
                Arrays.copyOfRange(epData, 0, 32),  // 前32字节
            };
        }
        
        if (epData.length >= 48) {
            ivOptions = new byte[][] {
                Arrays.copyOfRange(epData, 32, 48),  // 字节32-48
                Arrays.copyOfRange(dataEncrypted, 0, 16),  // data的前16字节
            };
        }
        
        // 尝试所有组合
        int testNum = 1;
        for (byte[] key : keyOptions) {
            for (byte[] iv : ivOptions) {
                System.out.println("测试 " + testNum++ + ":");
                System.out.println("  密钥: " + bytesToHex(Arrays.copyOfRange(key, 0, 16)) + "...");
                System.out.println("  IV:   " + bytesToHex(iv));
                
                try {
                    SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
                    IvParameterSpec ivSpec = new IvParameterSpec(iv);
                    
                    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                    cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
                    byte[] decrypted = cipher.doFinal(dataEncrypted);
                    
                    System.out.println("  ✅ AES解密成功！长度: " + decrypted.length + " 字节");
                    
                    // 尝试zlib解压
                    try {
                        byte[] decompressed = zlibDecompress(decrypted);
                        System.out.println("  ✅ zlib解压成功！长度: " + decompressed.length + " 字节");
                        
                        String json = new String(decompressed, "UTF-8");
                        System.out.println("\n" + "🎉".repeat(40));
                        System.out.println("成功解密data！完整的加密流程已破解！");
                        System.out.println("🎉".repeat(40));
                        System.out.println("\ndata明文内容:");
                        System.out.println(json);
                        System.out.println("\n" + "=".repeat(80));
                        
                        return;  // 成功后退出
                        
                    } catch (Exception e) {
                        System.out.println("  ❌ zlib解压失败: " + e.getMessage());
                    }
                    
                } catch (javax.crypto.BadPaddingException e) {
                    System.out.println("  ❌ 填充错误（密钥或IV不正确）");
                } catch (Exception e) {
                    System.out.println("  ❌ 解密失败: " + e.getMessage());
                }
                System.out.println();
            }
        }
        
        System.out.println("❌ 所有组合都失败了");
    }
    
    private static byte[] zlibDecompress(byte[] data) throws Exception {
        Inflater inflater = new Inflater();
        inflater.setInput(data);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(data.length);
        byte[] buffer = new byte[1024];
        while (!inflater.finished()) {
            int count = inflater.inflate(buffer);
            outputStream.write(buffer, 0, count);
        }
        outputStream.close();
        return outputStream.toByteArray();
    }
    
    private static void printHexDump(byte[] data) {
        for (int i = 0; i < data.length; i += 16) {
            System.out.print(String.format("%04X: ", i));
            
            for (int j = 0; j < 16; j++) {
                if (i + j < data.length) {
                    System.out.print(String.format("%02X ", data[i + j]));
                } else {
                    System.out.print("   ");
                }
                if (j == 7) System.out.print(" ");
            }
            
            System.out.print(" |");
            for (int j = 0; j < 16 && i + j < data.length; j++) {
                byte b = data[i + j];
                System.out.print((b >= 32 && b < 127) ? (char) b : '.');
            }
            System.out.println("|");
        }
    }
    
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}



